/**
 * JAVACC DEMO 1.0
 */
package com.apache.info.service.plugins;

import com.alibaba.druid.pool.DruidDataSource;
import com.apache.api.manager.PluginConnector;
import com.apache.api.vo.ParamsVo;
import com.apache.cache.util.Validator;
import com.apache.database.datasource.ConnctionData;
import com.apache.database.datasource.DynamicDataSource;
import com.apache.database.datasource.DynamicDataSourceHolder;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.exception.BusinessException;
import com.apache.info.entity.PubMetadata;
import com.apache.info.entity.PubSortInfo;
import com.apache.info.manager.InfoReleaseManager;
import com.apache.info.util.MessageUtil;
import com.apache.tools.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * description:  动态修改表操作
 *
 * @author Hou Dayu 创建时间：2016-8-28
 */
public class DynamicUpdateTablePluginImpl implements PluginConnector {
	private Logger log = LoggerFactory.getLogger(getClass());
	private InfoReleaseManager infoReleaseManager;

	private IDao pubMetadataDao;

	/**
	 * TODO 动态修改表插件实现.
	 *
	 * @see PluginConnector#execute(ParamsVo)
	 */
	public Object execute(ParamsVo vo) throws Exception {
		String key = vo.getMethodKey();
		String sortId = String.valueOf(vo.getParams("sortId"));
		String cacheKey = "pubSortInfo_" + sortId;
		MethodParam param = new MethodParam("ById", cacheKey, "", PubSortInfo.class.getName());
		param.setParams("sortId", sortId);
		PubSortInfo sort = (PubSortInfo) pubMetadataDao.selectSingle(param);
		String sysName = StrUtil.doNull(sort.getSysName(), "plateform");
		DynamicDataSourceHolder.putDataSource(Validator.getDefaultStr(sysName, "default"));
		if ("1".equals(sort.getSortStatus())) {
			DruidDataSource bds = DynamicDataSource.getInstance().getDataSource(sysName);//ConnctionData.getInstance().getDataSource(sysName);
			//			if (null == bds) {
			//				bds = ConnctionData.getInstance().getDataSource("plateform");
			//			}
			String dbType = MessageUtil.getDatabastType(sort.getSysName(), bds.getDriverClassName());
			String sql = null;

			//            ParamsVo pvo = new ParamsVo();
			//            pvo.setParams("database_type", sysName);
			PubMetadata metadata = (PubMetadata) vo.getParams("metadata");
			if ("F".equals(metadata.getReserved2()))
				return true;
			if (Validator.isNull(key) || "update".equals(key)) {//添加新字段
				sql = getSql(sort.getInfoTableName(), metadata, dbType);
				//                pvo.setParams("dyncSql", sql);
				//                return infoReleaseManager.editInfo(pvo);
			} else if ("del".equals(key)) {//删除字段
				sql = "ALTER TABLE " + sort.getInfoTableName() + " DROP COLUMN " + metadata.getDataShortName();
				//                pvo.setParams("dyncSql", sql);
				//                return infoReleaseManager.deleteInfo(pvo);
			} else if ("modify".equals(key)) {//修改字段长度
				PubMetadata old = (PubMetadata) vo.getParams("old");
				sql = modifySql(sort.getInfoTableName(), metadata, old, dbType);
				//                if (Validator.isNotNull(sql)) {
				//                    pvo.setParams("dyncSql", sql);
				//                    return infoReleaseManager.editInfo(pvo);
				//                }
			}
			if (StrUtil.isNull(sql))
				return false;
			try {
				Connection con = bds.getConnection();
				log.info(sql.toString());
				if ("modify".equals(key) && "oracle".equals(dbType)) {//修改字段名称
					PubMetadata old = (PubMetadata) vo.getParams("old");
					if (!old.getDataShortName().equalsIgnoreCase(metadata.getDataShortName())) {
						String sqlstr = "ALTER TABLE " + sort.getInfoTableName()+ " rename "+ old.getDataShortName()+" to "+metadata.getDataShortName();
						Statement stmt = null;//stmt用于发送sql语句到数据库并执行sql语句
						try {
							con.setAutoCommit(true);
							stmt = con.createStatement();
							stmt.addBatch(sqlstr);
							stmt.addBatch(sql);
							stmt.executeBatch();
						} catch (SQLException e) {
							throw new BusinessException("执行sql异常:" + e.getMessage());
						} finally {
							ConnctionData.getInstance().close(con, stmt, null);
						}
					}
				}else {
					return ConnctionData.getInstance().execute(con, sql);
				}
			}catch (SQLException e){
				DynamicDataSource.getInstance().removeDataSource(sysName);
				return false;
			}
		}
		return true;
	}

	private String modifySql(String tableName, PubMetadata pm, PubMetadata old, String dbType) {
		StringBuilder sql = new StringBuilder("ALTER TABLE " + tableName);
		//        String dbType = ConfigUtil.getInstance().getValueByKey("jdbc.properties", "database_type");
		if ("oracle".equals(dbType)) {
			sql.append(" modify (" + pm.getDataShortName());
			if(!old.getDataType().equals(pm.getDataType()) && old.getDataLength()!= pm.getDataLength()) {
				sql.append(getDataType(pm, dbType));
			}
			//主键，非空，联合主键设置为不可空
			if ("1".equals(pm.getDataRestrict()) || "2".equals(pm.getDataRestrict()) || "4".equals(pm.getDataRestrict())) {
				sql.append(" not null ");
			} else {
				sql.append(" null ");
			}
			sql.append(")");
		} else {
			if (old.getDataShortName().equalsIgnoreCase(pm.getDataShortName())) {//施工方
				sql.append(" modify " + pm.getDataShortName());
				if(!old.getDataType().equals(pm.getDataType()) || old.getDataLength()!= pm.getDataLength()) {
					sql.append(getDataType(pm, dbType));
				}
			} else {//修改字段名称，此时一定要重新指定该字段的类型
				sql.append(" CHANGE " + old.getDataShortName() + " " + pm.getDataShortName());
				sql.append(getDataType(pm,dbType));
			}
			//主键，非空，联合主键设置为不可空
			if ("1".equals(pm.getDataRestrict()) || "2".equals(pm.getDataRestrict()) || "4".equals(pm.getDataRestrict())) {
				sql.append(" not null");
			} else {
				sql.append(" null");
			}
		}
		return sql.toString();
	}

	private String getSql(String tableName, PubMetadata pm, String dbType) {
		StringBuilder sql = new StringBuilder("ALTER TABLE " + tableName + " ADD " + pm.getDataShortName() + " ");
		//        String dbType = ConfigUtil.getInstance().getValueByKey("jdbc.properties", "database_type");
		sql.append(getDataType(pm, dbType));
		if ("1".equals(pm.getDataRestrict()) || "2".equals(pm.getDataRestrict()) || "4".equals(pm.getDataRestrict())) {
			sql.append(" not null ");
		}
		return sql.toString();
	}

	private String getDataType(PubMetadata pm, String dbType) {
		StringBuilder sql = new StringBuilder();
		if ("1".equals(pm.getDataType()) || "2".equals(pm.getDataType())) {
			if ("oracle".equals(dbType)) {
				sql.append(" number(" + pm.getDataLength() + ") ");
			} else {
				if ("1".equals(pm.getDataType())) {
					sql.append(" int ");
				} else if ("2".equals(pm.getDataType())) {
					sql.append(" bigint ");
				}
			}
		} else if ("3".equals(pm.getDataType())) {
			if ("oracle".equals(dbType)) {
				sql.append(" number(" + pm.getDataLength() + ",6) ");
			} else {
				sql.append(" float (" + pm.getDataLength() + ",6)");
			}
		} else if ("4".equals(pm.getDataType())) {
			sql.append(" char(" + (pm.getDataLength()>255?255:pm.getDataLength()) + ") ");
		} else if ("6".equals(pm.getDataType())) {
			if ("oracle".equals(dbType)) {
				sql.append(" date ");
			} else {
				sql.append(" datetime ");
			}
		} else if ("7".equals(pm.getDataType())) {
			if ("oracle".equals(dbType)) {
				log.error("暂不支持！");
			} else {
				sql.append(" longtext ");
			}
		} else if ("8".equals(pm.getDataType())) {
			if ("oracle".equals(dbType)) {
				sql.append(" number(" + pm.getDataLength() + ",6) ");
			} else {
				sql.append(" decimal(" + pm.getDataLength() + ") ");
			}
		}  else {
			if ("oracle".equals(dbType)) {
				sql.append(" varchar2(" + pm.getDataLength() + ") ");
			} else {
				sql.append(" varchar(" + pm.getDataLength() + ") ");
			}
		}
		return sql.toString();
	}

	public void setInfoReleaseManager(InfoReleaseManager infoReleaseManager) {
		this.infoReleaseManager = infoReleaseManager;
	}

	public void setPubMetadataDao(IDao pubMetadataDao) {
		this.pubMetadataDao = pubMetadataDao;
	}

}
